home *** CD-ROM | disk | FTP | other *** search
Text File | 2004-04-18 | 47.8 KB | 1,646 lines |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is The JavaScript Debugger.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Robert Ginda, <rginda@netscape.com>, original author
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
- const VMGR_VURL_SCHEME = "x-vloc:";
- const VMGR_SCHEME_LEN = VMGR_VURL_SCHEME.length;
-
- const VMGR_HIDDEN = "hidden";
- const VMGR_NEW = "new";
- const VMGR_MAINWINDOW = "mainwindow";
- const VMGR_GUTTER = "gutter";
-
- const VMGR_VURL_HIDDEN = VMGR_VURL_SCHEME + "/" + VMGR_HIDDEN;
- const VMGR_VURL_NEW = VMGR_VURL_SCHEME + "/" + VMGR_NEW;
- const VMGR_VURL_MAINWINDOW = VMGR_VURL_SCHEME + "/" + VMGR_MAINWINDOW;
- const VMGR_VURL_GUTTER = VMGR_VURL_MAINWINDOW + "/gutter";
- const VMGR_DEFAULT_CONTAINER = "initial-container";
-
- var VMGR_GUTTER_CONTAINER = VMGR_VURL_MAINWINDOW + "?target=container&" +
- "id=" + VMGR_GUTTER + "&type=vertical";
-
- function ViewManager(commandManager, mainWindow)
- {
- this.commandManager = commandManager;
- this.multiMoveDepth = 0;
- this.floaterSequence = 0;
- this.containerSequence = 0;
- this.dirtyContainers = new Object();
- this.windows = new Object();
- this.mainWindow = mainWindow;
- this.windows[VMGR_MAINWINDOW] = mainWindow;
- this.views = new Object();
- }
-
- ViewManager.prototype.realizeViews =
- function vmgr_realizeviews (views)
- {
- for (var v in views)
- this.realizeView(views[v]);
- }
-
- ViewManager.prototype.realizeView =
- function vmgr_realizeview (view)
- {
- var entry;
- var key = view.viewId;
- this.views[key] = view;
- if ("init" in view && typeof view.init == "function")
- view.init();
-
- var toggleName = "toggle-" + key;
- if (!(key in this.commandManager.commands))
- {
- entry = [toggleName, "toggle-view " + key, CMD_CONSOLE];
-
- if ("cmdary" in view)
- view.cmdary.unshift(entry);
- else
- view.cmdary = [entry];
- }
-
- if ("cmdary" in view)
- {
- var commands = this.commandManager.defineCommands(view.cmdary);
- for (var i in this.windows)
- this.commandManager.installKeys (this.windows[i].document,
- commands);
- view.commands = commands;
- }
- if ("hooks" in view)
- this.commandManager.addHooks (view.hooks, key);
- }
-
- ViewManager.prototype.unrealizeViews =
- function vmgr_unrealizeviews (views)
- {
- for (var v in views)
- this.unrealizeView(views[v]);
- }
-
- ViewManager.prototype.unrealizeView =
- function vmgr_unrealizeview (view)
- {
- if ("commands" in view)
- this.commandManager.uninstallKeys(view.commands);
- if ("hooks" in view)
- this.commandManager.removeHooks (view.hooks, view.viewId);
-
- if ("destroy" in view && typeof view.destroy == "function")
- view.destroy();
-
- delete this.views[view.viewId];
- }
-
- ViewManager.prototype.startMultiMove =
- function vmrg_startmm()
- {
- ++this.multiMoveDepth;
- }
-
- ViewManager.prototype.endMultiMove =
- function vmrg_endmm()
- {
- --this.multiMoveDepth;
-
- ASSERT(this.multiMoveDepth >= 0, "mismatched multi move calls: " +
- this.multiMoveDepth);
-
- var container;
-
- if (!this.multiMoveDepth)
- {
- // close any empty windows that may have been left open during the
- // multi move.
- for (var w in this.windows)
- {
- if (w != VMGR_MAINWINDOW)
- {
- var window = this.windows[w];
- container =
- window.document.getElementById(VMGR_DEFAULT_CONTAINER);
- if (container && container.viewCount == 0)
- window.close();
- }
- }
-
- // deal with any single child tab containers too
- for (var viewId in this.views)
- {
- var view = this.views[viewId];
- if ("currentContent" in view && view.currentContent)
- {
- container = view.currentContent.parentNode;
- if (container.getAttribute("type") == "tab" &&
- container.viewCount == 1)
- {
- var parentLocation = this.computeLocation(container);
- container.viewCount = 0;
- this.moveView(parentLocation, viewId);
- container.parentNode.removeChild(container);
- }
- }
- }
- }
- }
-
- ViewManager.prototype.getWindowById =
- function vmgr_getwindow (windowId)
- {
- if (windowId in this.windows)
- return this.windows[windowId];
-
- return null;
- }
-
- ViewManager.prototype.createWindow =
- function vmgr_createwindow (windowId, cb)
- {
- var viewManager = this;
-
- function onWindowLoaded (window)
- {
- var cm = viewManager.commandManager;
- cm.installKeys (window.document, cm.commands);
- if (typeof cb == "function")
- cb(window);
- };
-
- if (!ASSERT(!(windowId in this.windows), "window " + windowId +
- " already exists"))
- {
- return null;
- }
-
- var win = openDialog ("chrome://venkman/content/venkman-floater.xul?id=" +
- encodeURIComponent(windowId), "_blank",
- "chrome,menubar,toolbar,resizable,dialog=no",
- onWindowLoaded);
- this.windows[windowId] = win;
- return win;
- }
-
- ViewManager.prototype.destroyWindows =
- function vmgr_destroywindows ()
- {
- this.startMultiMove();
-
- for (var w in this.windows)
- {
- if (w == VMGR_MAINWINDOW)
- this.destroyWindow(w);
- else
- this.windows[w].close();
- }
-
- this.endMultiMove();
- }
-
- ViewManager.prototype.destroyWindow =
- function vmgr_destroywindow (windowId)
- {
- if (!ASSERT(windowId in this.windows, "unknown window id"))
- return;
-
- var document = this.windows[windowId].document;
-
- for (var viewId in this.views)
- {
- try
- {
- var view = this.views[viewId];
-
- if ("currentContent" in view &&
- view.currentContent.ownerDocument == document)
- {
- this.moveViewURL(VMGR_VURL_HIDDEN, viewId);
- }
- }
- catch (ex)
- {
- dd ("caught exception while moving view ``" + ex + "''");
- }
- }
-
- var container = document.getElementById (VMGR_DEFAULT_CONTAINER);
- var child = container.firstChild;
- while (child)
- {
- var next = child.nextSibling;
- container.removeChild (child);
- child = next;
- }
-
- if (windowId != VMGR_MAINWINDOW)
- delete this.windows[windowId];
- }
-
- ViewManager.prototype.destroyContainer =
- function vmgr_destroycontainer (container)
- {
- content = container.firstChild;
-
- while (content)
- {
- if (content.hasAttribute("grout"))
- {
- content.parentNode.removeChild(content);
- }
- else
- {
- if (content.localName == "viewcontainer")
- {
- this.destroyContainer(content);
- }
- else
- {
- var viewId = content.getAttribute("id");
- this.moveViewURL(VMGR_VURL_HIDDEN, viewId);
- }
- }
-
- content = container.firstChild;
- }
-
- container.parentNode.removeChild(container);
- }
-
- ViewManager.prototype.changeContainer =
- function vmgr_changecontainer (container, newType)
- {
- if (!ASSERT(newType != container.getAttribute("type"),
- "requested useless change, ``" + newType + "''"))
- {
- return;
- }
-
- this.hideContainer(container);
- container.setAttribute("type", newType);
- this.showContainer(container);
-
- this.groutContainer(container);
- }
-
- ViewManager.prototype.createContainer =
- function vmgr_createcontainer (parsedLocation, containerId, type)
- {
- if (!type)
- type = "vertical";
-
- var parentContainer = this.getLocation(parsedLocation);
-
- if (!ASSERT(parentContainer, "location is hidden or does not exist"))
- return null;
-
- var document = parentContainer.ownerDocument;
- var container = document.createElement("viewcontainer");
- container.setAttribute ("id", containerId);
- container.setAttribute ("flex", "1");
- container.setAttribute ("type", type);
- if ("width" in parsedLocation)
- container.setAttribute ("width", parsedLocation.width);
- if ("height" in parsedLocation)
- container.setAttribute ("height", parsedLocation.height);
- container.setAttribute ("collapsed", "true");
- var before;
- if ("before" in parsedLocation)
- before = getChildById(parentContainer, parsedLocation.before);
- parentContainer.insertBefore(container, before);
- this.groutContainer(parentContainer);
-
- return container;
- }
-
- /*
- * x-vloc:/<window-id>[/<container-id>][?<option>[&<option>...]]
- *
- * <option> is one of...
- * before=<view-id>
- * type=(horizontal|vertical|tab)
- * id=(<view-id>|<container-id>)
- * target=(view|container)
- * width=<number>
- * height=<number>
- *
- * parseResult
- * +- url
- * +- windowId
- * +- containerId
- * +- <option>
- * +- ...
- */
-
- ViewManager.prototype.parseLocation =
- function vmgr_parselocation (locationURL)
- {
- var parseResult;
- var ary;
-
- if (locationURL.indexOf(VMGR_VURL_SCHEME) != 0)
- return null;
-
- ary =
- locationURL.substr(VMGR_SCHEME_LEN).match(/([^\/?]+)(?:\/([^\/?]+))?/);
- if (!ary)
- return null;
-
- parseResult = {
- url: locationURL,
- windowId: ary[1],
- containerId: arrayHasElementAt(ary, 2) ? ary[2] : VMGR_DEFAULT_CONTAINER
- };
-
- var rest = RegExp.rightContext.substr(1);
-
- ary = rest.match(/([^&]+)/);
-
- while (ary)
- {
- rest = RegExp.rightContext.substr(1);
- var assignment = ary[1];
- ary = assignment.match(/(.+)=(.*)/);
- if (ASSERT(ary, "error parsing ``" + assignment + "'' from " +
- locationURL))
- {
- /* only set the property the first time we see it */
- if (arrayHasElementAt(ary, 2) && !(ary[1] in parseResult))
- parseResult[ary[1]] = ary[2];
- }
- ary = rest.match(/([^&]+)/);
- }
-
- if (parseResult.windowId == VMGR_NEW)
- {
- var id = "floater-" + this.floaterSequence++;
-
- while (id in this.windows)
- id = "floater-" + this.floaterSequence++;
-
- parseResult.windowId = id;
- }
-
- //dd (dumpObjectTree(parseResult));
- return parseResult;
- }
-
- ViewManager.prototype.getWindowId =
- function getwindowid (window)
- {
- for (var m in this.windows)
- {
- if (this.windows[m] == window)
- return m;
- }
-
- ASSERT (0, "unknown window");
- return null;
- }
-
- ViewManager.prototype.getLayoutState =
- function vmgr_getlayout ()
- {
- var ary = new Array();
-
- for (var w in this.windows)
- {
- var container =
- this.windows[w].document.getElementById (VMGR_DEFAULT_CONTAINER);
- this.getContainerContents (container, true, ary);
- }
-
- return ary;
- }
-
- ViewManager.prototype.getContainerContents =
- function vmgr_getcontents (container, recurse, ary)
- {
- if (!ary)
- ary = new Array();
- var child = container.firstChild;
-
- while (child)
- {
- if (child.localName == "viewcontainer" && "viewCount" in child &&
- child.viewCount > 0)
- {
- ary.push (this.computeLocation(child));
- if (recurse)
- this.getContainerContents(child, true, ary);
- }
- else if (child.localName == "floatingview")
- {
- ary.push (this.computeLocation(child));
- }
- child = child.nextSibling;
- }
-
- return ary;
- }
-
- ViewManager.prototype.reconstituteVURLs =
- function vmgr_remake (ary, cb, startIndex, recalled)
- {
- var viewManager = this;
-
- function onWindowLoaded (window)
- {
- viewManager.reconstituteVURLs (ary, cb, i, true);
- };
-
- if (!startIndex)
- startIndex = 0;
-
- if (!recalled)
- this.startMultiMove();
-
- for (var i = startIndex; i < ary.length; ++i)
- {
- var parsedLocation = this.parseLocation (ary[i]);
- if (!ASSERT(parsedLocation, "can't parse " + ary[i]) ||
- !ASSERT("target" in parsedLocation, "no target in " + ary[i]) ||
- !ASSERT("id" in parsedLocation, "no id in " + ary[i]))
- {
- continue;
- }
-
- if (parsedLocation.target == "container")
- {
- if (!(parsedLocation.windowId in this.windows))
- {
- //dd ("loading window " + parsedLocation.windowId);
- this.createWindow (parsedLocation.windowId, onWindowLoaded);
- return;
- }
-
- if (!ASSERT("type" in parsedLocation, "no type in " + ary[i]))
- parsedLocation.type = "vertical";
- this.createContainer (parsedLocation, parsedLocation.id,
- parsedLocation.type);
- }
- else if (parsedLocation.target == "view")
- {
- var height = ("height" in parsedLocation ?
- parsedLocation.height : null);
- var width = ("width" in parsedLocation ?
- parsedLocation.width : null);
- this.moveView (parsedLocation, parsedLocation.id, height, width);
- }
- else
- {
- ASSERT(0, "unknown target in " + ary[i]);
- }
- }
-
- if (typeof cb == "function")
- cb();
-
- this.endMultiMove();
- }
-
- ViewManager.prototype.computeLocation =
- function vmgr_computelocation (element)
- {
- if (!ASSERT(element, "missig parameter"))
- return null;
-
- if (!element.parentNode)
- return VMGR_VURL_HIDDEN;
-
- var target;
- var containerId;
- var type;
-
- if (element.localName == "floatingview")
- {
- target = "view";
- if (element.parentNode.localName != "viewcontainer")
- containerId = VMGR_HIDDEN;
- else
- containerId = element.parentNode.getAttribute("id");
- }
- else if (element.localName == "viewcontainer")
- {
- target = "container";
- containerId = element.parentNode.getAttribute("id");
- type = element.getAttribute("type");
- }
- else
- {
- ASSERT(0, "can't get location for unknown element " +
- element.localName);
- return null;
- }
-
- var before;
-
- if (containerId != VMGR_HIDDEN)
- {
- var beforeNode = element.nextSibling;
- if (beforeNode)
- {
- if (beforeNode.hasAttribute("grout"))
- beforeNode = beforeNode.nextSibling;
-
- if (ASSERT(beforeNode, "nothing before the grout?"))
- before = beforeNode.getAttribute("id");
- }
- }
-
- var windowId = this.getWindowId(element.ownerWindow);
- var id = element.getAttribute("id");
- var height = element.getAttribute("height");
- var width = element.getAttribute("width");
- var url = VMGR_VURL_SCHEME + "/" + windowId + "/" + containerId +
- "?target=" + target + "&id=" + id;
- if (height)
- url += "&height=" + height;
- if (width)
- url += "&width=" + width;
- if (before)
- url += "&before=" + before;
- if (type)
- url += "&type=" + type;
-
- var result = new String(url);
- result.url = url;
- result.windowId = windowId;
- result.containerId = containerId;
- result.target = target;
- result.id = id;
- result.height = height;
- result.width = width;
- result.before = before;
- result.type = type;
-
- return result;
- }
-
- ViewManager.prototype.locationExists =
- function vmgr_islocation (parsedLocation)
- {
- if (parsedLocation.windowId == VMGR_HIDDEN)
- return true;
-
- if (this.getLocation(parsedLocation))
- return true;
-
- return false;
- }
-
- ViewManager.prototype.getLocation =
- function vmgr_getlocation (parsedLocation)
- {
- if (parsedLocation.windowId == VMGR_HIDDEN)
- {
- //dd ("getLocation: location is hidden");
- return null;
- }
-
- var window = this.getWindowById(parsedLocation.windowId);
- if (!ASSERT(window, "unknown window id " + parsedLocation.windowId))
- return false;
-
- if (!parsedLocation.containerId)
- parsedLocation.containerId = VMGR_DEFAULT_CONTAINER;
-
- var container = window.document.getElementById(parsedLocation.containerId);
- return container;
- }
-
- ViewManager.prototype.ensureLocation =
- function vmgr_ensurelocation (parsedLocation, cb)
- {
- var viewManager = this;
-
- function onWindowLoaded (window)
- {
- var container =
- window.document.getElementById (parsedLocation.containerId);
- if (!container && parsedLocation.containerId == VMGR_GUTTER)
- {
- viewManager.reconstituteVURLs ([VMGR_GUTTER_CONTAINER]);
- container =
- window.document.getElementById (parsedLocation.containerId);
- }
- cb (window, container);
- };
-
- if (parsedLocation.windowId == VMGR_HIDDEN)
- {
- cb(null, null);
- return;
- }
-
- var window = this.getWindowById(parsedLocation.windowId);
- if (window)
- {
- onWindowLoaded(window);
- return;
- }
-
- this.createWindow (parsedLocation.windowId, onWindowLoaded);
- }
-
- /**
- * This only half-assed affects the contents. It calls the show/hide events
- * on the contained views, but does not actually re-home the content. This
- * should only be used to quickly move views within the same window.
- */
- ViewManager.prototype.showContainer =
- function vbgr_showctr (container, state)
- {
- if (typeof state == "undefined")
- state = true;
-
- var content = container.firstChild;
- while (content)
- {
- if (content.localName == "floatingview")
- {
- var viewId = content.getAttribute("id");
- if (!ASSERT(viewId in this.views, "unknown view"))
- {
- content = content.nextSibling;
- continue;
- }
-
- if (state)
- this.views[viewId].onShow();
- else
- this.views[viewId].onHide();
- }
- else if (content.localName == "viewcontainer")
- {
- this.showContainer(content, state);
- }
-
- content = content.nextSibling;
- }
- }
-
- ViewManager.prototype.hideContainer =
- function vbgr_hidectr (container)
- {
- this.showContainer(container, false);
- }
-
- ViewManager.prototype.moveContainer =
- function vmgr_movectr (parsedLocation, sourceContainer)
- {
- var viewManager = this;
-
- function onLocationFound (window, container)
- {
- if (!window)
- {
- ASSERT(false, "not implemented");
- return;
- // everything gets hidden
- }
-
- var beforeNode;
- if ("before" in parsedLocation)
- beforeNode = window.document.getElementById(parsedLocation.before);
-
- if (!container)
- {
- /* container does not exist. */
- if (beforeNode)
- {
- // if we know who it's supposed to be before, then drop it
- // there.
- container = beforeNode.parentNode;
- }
- else
- {
- // otherwise, toss it in the gutter
- var gutterContainer = Clone(parsedLocation);
- gutterContainer.containerId = VMGR_GUTTER;
- container = viewManager.getLocation(gutterContainer);
- if (!container)
- {
- gutterContainer.containerId = VMGR_DEFAULT_CONTAINER;
- container = viewManager.createContainer(gutterContainer,
- VMGR_GUTTER,
- "vertical");
- }
- }
- if (!ASSERT(container, "can't locate default container"))
- return;
- }
- else if (beforeNode && beforeNode.parentNode != container)
- {
- //dd ("before is not in container");
- /* container portion of url wins in a mismatch situation */
- beforeNode = null;
- }
-
- viewManager.hideContainer(sourceContainer);
-
- var previousParent = sourceContainer.parentNode;
- previousParent.removeChild(sourceContainer);
- viewManager.groutContainer(previousParent);
-
- dd ("beforeNode is " + (beforeNode ? beforeNode.getAttribute("id") :
- null));
-
- container.insertBefore(sourceContainer, beforeNode);
- viewManager.showContainer(sourceContainer);
- viewManager.groutContainer(sourceContainer);
- };
-
- var sourceLocation = this.computeLocation(sourceContainer);
- if (!ASSERT (sourceLocation.windowId == parsedLocation.windowId,
- "moving containers between windows is not supported"))
- {
- return;
- }
-
- this.ensureLocation (parsedLocation, onLocationFound);
- }
-
- ViewManager.prototype.moveViewURL =
- function vmgr_moveurl (locationURL, viewId)
- {
- var parsedLocation = this.parseLocation(locationURL);
- if (!ASSERT(parsedLocation, "can't parse " + locationURL))
- return;
-
- this.moveView(parsedLocation, viewId);
- }
-
- ViewManager.prototype.moveView =
- function vmgr_move (parsedLocation, viewId, height, width)
- {
- var viewManager = this;
-
- function moveContent (content, newParent, before)
- {
- if (!("originalParent" in content))
- {
- if (!ASSERT(content.parentNode, "no original parent to record"))
- return;
- content.originalParent = content.parentNode;
- }
-
- //dd ("OFF moveContent {");
-
- var previousParent = content.parentNode;
- previousParent.removeChild(content);
- if (previousParent.localName == "viewcontainer")
- viewManager.groutContainer (previousParent);
-
- if (newParent)
- {
- //dd ("placing in new parent");
- newParent.insertBefore (content, before);
- viewManager.groutContainer (newParent);
- }
- else
- {
- //dd ("hiding");
- content.originalParent.appendChild(content);
- content.setAttribute ("containertype", "hidden");
- }
-
- //dd ("}");
- };
-
- function onLocationFound (window, container)
- {
- if (!window)
- {
- /* view needs to be hidden. */
- if (currentContent)
- {
- if ("onHide" in view)
- view.onHide();
-
- if ("onViewRemoved" in view.currentContent.ownerWindow)
- view.currentContent.ownerWindow.onViewRemoved(view);
-
- moveContent (view.currentContent, null);
- delete view.currentContent;
- }
- return;
- }
-
- var content = window.document.getElementById(viewId);
- if (!ASSERT(content, "no content for ``" + viewId + "'' found in " +
- parsedLocation.windowId))
- {
- return;
- }
-
- var beforeNode;
- if ("before" in parsedLocation)
- {
- beforeNode = window.document.getElementById(parsedLocation.before);
- if (beforeNode &&
- beforeNode.parentNode.localName != "viewcontainer")
- {
- beforeNode = null;
- }
- }
-
- if (!container)
- {
- /* container does not exist. */
- if (beforeNode)
- {
- // if we know who it's supposed to be before, then drop it
- // there.
- container = beforeNode.parentNode;
- }
- else
- {
- // otherwise, toss it in the gutter
- var gutterContainer = Clone(parsedLocation);
- gutterContainer.containerId = VMGR_GUTTER;
- container = viewManager.getLocation(gutterContainer);
- if (!container)
- {
- gutterContainer.containerId = VMGR_DEFAULT_CONTAINER;
- container = viewManager.createContainer(gutterContainer,
- VMGR_GUTTER,
- "vertical");
- }
- }
- if (!ASSERT(container, "can't locate default container"))
- return;
- }
- else if (beforeNode && beforeNode.parentNode != container)
- {
- //dd ("before is not in container");
- /* container portion of url wins in a mismatch situation */
- beforeNode = null;
- }
-
- if (currentContent)
- {
- //dd ("have content");
- /* view is already visible, fire an onHide(). If we're destined for
- * a new document, return the current content to it's hiding place.
- */
- if (beforeNode == currentContent ||
- (currentContent.nextSibling == beforeNode &&
- container == currentContent.parentNode))
- {
- /* unless we're already where we are supposed to be. */
- return;
- }
-
- if ("onHide" in view)
- view.onHide();
-
- if ("onViewRemoved" in currentContent.ownerWindow)
- currentContent.ownerWindow.onViewRemoved(view);
-
- if (currentContent != content)
- {
- //dd ("returning content to home");
- moveContent (currentContent, null);
- }
- }
-
- moveContent (content, container, beforeNode);
- view.currentContent = content;
- if (height)
- content.setAttribute ("height", height);
- if (width)
- content.setAttribute ("width", width);
-
- if ("onShow" in view)
- view.onShow();
-
- if ("onViewAdded" in window)
- window.onViewAdded(view);
- };
-
- var view = this.views[viewId];
- var currentContent = ("currentContent" in view ?
- view.currentContent : null);
- if (currentContent && currentContent.ownerWindow == this.mainWindow)
- view.previousLocation = this.computeLocation(currentContent);
-
- this.ensureLocation (parsedLocation, onLocationFound);
- }
-
- ViewManager.prototype.groutContainer =
- function vmgr_groutcontainer (container)
- {
- if (!container.parentNode)
- return;
-
- var type = container.getAttribute ("type");
-
- if (!ASSERT(type in this.groutFunctions, "unknown container type ``" +
- type + "''"))
- {
- return;
- }
-
- if (!container.hasAttribute("grout-in-progress"))
- {
- container.setAttribute("grout-in-progress", "true");
-
- this.groutFunctions[type](this, container);
-
- var location = this.computeLocation(container);
- if (location in this.dirtyContainers)
- delete this.dirtyContainers[location];
-
- container.removeAttribute("grout-in-progress");
- }
- }
-
- ViewManager.prototype.groutFunctions = new Object();
-
- ViewManager.prototype.groutFunctions["tab"] =
- function vmgr_grouttab (viewManager, container)
- {
- function onTabClick(event)
- {
- var target = event.target;
- while (target && target.localName != "little-tab")
- target = target.parentNode;
-
- var index = target.getAttribute("index");
- container.deck.selectedIndex = index;
- for (var i = 0; i < container.tabs.childNodes.length; ++i)
- container.tabs.childNodes[i].removeAttribute("selected");
-
- container.tabs.childNodes[index].setAttribute("selected", "true");
- };
-
- function closeWindow (window)
- {
- window.close();
- };
-
- if (!ASSERT(container, "null container"))
- return;
-
- ASSERT(container.localName == "viewcontainer",
- "Attempt to grout something that is not a view container");
-
- var content = container.firstChild;
- var document = container.ownerDocument;
- container.viewCount = 0;
-
- var lastSelected = container.deck.selectedIndex;
-
- while (content)
- {
- var nextContent = content.nextSibling;
-
- if (content.hasAttribute("grout"))
- {
- container.removeChild(content);
- }
- else
- {
- var viewId = content.getAttribute("id");
-
- if (!ASSERT(content.localName != "viewcontainer",
- "tab containers cannot contain other containers"))
- {
- viewManager.destroyContainer(content);
- content = nextContent;
- continue;
- }
-
- if (!ASSERT(viewId in viewManager.views, "unknown view id ``" +
- viewId + "''"))
- {
- content = nextContent;
- continue;
- }
-
- var view = viewManager.views[viewId];
-
- var tab = (container.viewCount >= container.tabs.childNodes.length)
- ? null : container.tabs.childNodes[container.viewCount];
- var label;
-
- if (!tab || tab.hasAttribute("needinit"))
- {
- if (!tab)
- tab = document.createElement("little-tab");
- else
- tab.removeAttribute("needinit");
-
- tab.setAttribute("index", container.viewCount);
- tab.setAttribute("flex", "1");
- container.tabs.appendChild(tab);
- tab.addEventListener("click", onTabClick, false);
- }
-
- tab.setAttribute("label", view.caption);
-
- ++container.viewCount;
- }
-
- content = nextContent;
- }
-
- if (container.parentNode.localName == "viewcontainer")
- viewManager.groutContainer(container.parentNode);
-
- if (container.viewCount == 0)
- {
- //dd ("tab container is empty, hiding");
- container.setAttribute("collapsed", "true");
- if (viewManager.multiMoveDepth == 0 &&
- container.parentNode.localName == "window" &&
- container.ownerWindow != viewManager.mainWindow &&
- !("isClosing" in container.ownerWindow) &&
- lastViewCount > 0)
- {
- setTimeout (closeWindow, 1, container.ownerWindow);
- //dd ("} no children, closing window");
- }
- return;
- }
-
- //dd ("unhiding tab container");
- container.removeAttribute("collapsed");
-
- if (container.viewCount == 1 && !viewManager.multiMoveDepth)
- {
- var parentLocation =
- viewManager.computeLocation(view.currentContent.parentNode);
- container.viewCount = 0;
- viewManager.moveView(parentLocation, viewId);
- container.parentNode.removeChild(container);
- return;
- }
-
- while (container.tabs.childNodes.length > container.viewCount)
- container.tabs.removeChild(container.tabs.lastChild);
-
- if (lastSelected >= container.viewCount)
- lastSelected = container.viewCount - 1;
-
- if (typeof lastSelected == "number" && lastSelected > 0)
- container.deck.selectedIndex = lastSelected;
- else
- container.tabs.firstChild.setAttribute("selected", "true");
-
- }
-
- ViewManager.prototype.groutFunctions["horizontal"] =
- ViewManager.prototype.groutFunctions["vertical"] =
- function vmgr_groutbox (viewManager, container)
- {
- function closeWindow (window)
- {
- window.close();
- };
-
- function isContainerEmpty (container)
- {
- var rv = container.localName == "viewcontainer" &&
- "viewCount" in container && container.viewCount == 0;
- //dd ("isContainerEmpty: " + container.getAttribute("id") + ": " + rv);
- return rv;
- };
-
- if (!ASSERT(container, "null container"))
- return;
-
- if (!ASSERT(container.parentNode, "container has no parent ``" +
- container.getAttribute("id") + "''"))
- {
- return;
- }
-
- ASSERT(container.localName == "viewcontainer",
- "Attempt to grout something that is not a view container");
-
- //dd ("OFF grouting: " + container.getAttribute("id") +" {");
-
- var lastViewCount = ("viewCount" in container) ? container.viewCount : 0;
- container.viewCount = 0;
- var doc = container.ownerDocument;
- var content = container.firstChild;
- var orient = container.getAttribute("type");
-
- var previousContent;
- var nextContent;
-
- while (content)
- {
- previousContent = content.previousSibling;
- nextContent = content.nextSibling;
-
- while (nextContent && nextContent.localName == "viewcontainer" &&
- isContainerEmpty(nextContent))
- {
- //skip over empty containers
- nextContent = nextContent.nextSibling;
- }
-
- while (previousContent &&
- previousContent.localName == "viewcontainer" &&
- isContainerEmpty(previousContent))
- {
- //skip over empty containers
- previousContent = previousContent.previousSibling;
- }
-
- if (content.hasAttribute("grout"))
- {
- if (!previousContent || !nextContent ||
- previousContent.hasAttribute("grout") ||
- nextContent.hasAttribute("grout") ||
- isContainerEmpty(previousContent))
- {
- container.removeChild(content);
- }
- else
- {
- content.setAttribute("orient", orient);
- }
- }
- else
- {
- if (content.localName == "floatingview")
- ++container.viewCount;
- else if (content.localName == "viewcontainer")
- {
- if ("viewCount" in content)
- container.viewCount += content.viewCount;
- //else
- //dd ("no viewCount in " + content.getAttribute("id"));
- }
-
- if (nextContent && !nextContent.hasAttribute("grout") &&
- !isContainerEmpty(nextContent) && !isContainerEmpty(content))
- {
- var collapse;
- if (content.hasAttribute("splitter-collapse"))
- collapse = content.getAttribute("splitter-collapse");
- else
- collapse = "after";
- var split = doc.createElement("splitter");
- split.setAttribute("grout", "true");
- split.setAttribute("collapse", collapse);
- split.appendChild(doc.createElement("grippy"));
- container.insertBefore(split, nextContent);
- }
- }
- content = nextContent;
- }
-
- if (previousContent && previousContent.hasAttribute("grout") &&
- isContainerEmpty(previousContent.nextSibling))
- {
- container.removeChild(previousContent);
- }
-
-
- if (isContainerEmpty(container))
- {
- //dd ("container is empty, hiding");
- container.setAttribute("collapsed", "true");
- if (viewManager.multiMoveDepth == 0 &&
- container.parentNode.localName == "window" &&
- container.ownerWindow != viewManager.mainWindow &&
- !("isClosing" in container.ownerWindow) &&
- lastViewCount > 0)
- {
- setTimeout (closeWindow, 1, container.ownerWindow);
- //dd ("} no children, closing window");
- return;
- }
- }
- else
- {
- //dd ("unhiding");
- container.removeAttribute("collapsed");
- }
-
- if (container.parentNode.localName == "viewcontainer")
- viewManager.groutContainer(container.parentNode);
-
- //dd ("} " + container.getAttribute("id") +
- // " view count: " + container.viewCount);
-
- }
-
- ViewManager.prototype.findFloatingView =
- function vmgr_findview (element)
- {
- while (element && element.localName != "floatingview")
- {
- if (element.localName == "little-tab")
- {
- // this is probably a tab from a tab view container
- var container = element.parentNode.parentNode.parentNode;
- if (container.localName == "viewcontainer")
- return container.childNodes[element.getAttribute("index")];
- }
-
- element = element.parentNode;
- }
-
- return element;
- }
-
- ViewManager.prototype.findViewTab =
- function vmgr_findtab (viewContent)
- {
- var container = viewContent.parentNode;
- if (!ASSERT (container.localName == "viewcontainer", "not part of a view"))
- return null;
-
- if (container.getAttribute("type") != "tab")
- return null;
-
- var len = container.childNodes.length;
- for (var i = 0; i < len; ++i)
- {
- if (container.childNodes[i] == viewContent)
- break;
- }
-
- if (!ASSERT(i < len, "view not in its container?"))
- return null;
-
- return container.tabs.childNodes[i];
- }
-
- ViewManager.prototype.getDropDirection =
- function vmgr_getdropdir (event, floatingView)
- {
- var eventX = event.screenX - floatingView.boxObject.screenX;
- var eventY = event.screenY - floatingView.boxObject.screenY;
- var viewW = floatingView.boxObject.width;
- var viewH = floatingView.boxObject.height;
-
- if ((event.target.localName == "image" &&
- event.target.getAttribute("class") == "view-title-pop"))
- {
- // dropping on the pop icon
- return "new-tab";
- }
-
- if (eventY > viewH)
- {
- // out of bounds we must be in the tab strip of a tab view
- var tab = this.findViewTab(floatingView);
- if (!ASSERT(tab, "view has no tab"))
- return "new-tab";
-
- if (event.screenX > tab.boxObject.screenX + (tab.boxObject.width / 2))
- return "next-tab";
-
- return "prev-tab";
- }
-
- var rv;
- var dir;
-
- var m = viewH / viewW;
- if (eventY < m * eventX)
- dir = -1;
- else
- dir = 1;
-
- m = -m;
-
- if (eventY < m * eventX + viewH)
- {
- if (dir < 0)
- rv = "up";
- else
- rv = "left";
- }
- else
- {
- if (dir < 0)
- rv = "right";
- else
- rv = "down";
- }
-
- return rv;
- }
-
- ViewManager.prototype.onDragStart =
- function vmgr_dragstart (event, transferData, action)
- {
- var floatingView = this.findFloatingView (event.originalTarget);
- if (!floatingView)
- return false;
-
- var viewId = floatingView.getAttribute("id");
- if (!ASSERT(viewId in this.views, "unknown view " + viewId))
- return false;
-
- var view = this.views[viewId];
-
- if (!ASSERT("currentContent" in view, "view is not visible " + viewId))
- return false;
-
- var locationURL = this.computeLocation (view.currentContent);
- transferData.data = new TransferData();
- transferData.data.addDataForFlavour("text/x-vloc", locationURL);
-
- return true;
- }
-
- ViewManager.prototype.getSupportedFlavours =
- function vmgr_nicename ()
- {
- var flavours = new FlavourSet();
- flavours.appendFlavour("text/x-vloc");
- return flavours;
- }
-
- ViewManager.prototype.onViewDragOver =
- function vmgr_dragover (event, flavor, session)
- {
- session.canDrop = false;
-
- if (flavor.contentType != "text/x-vloc")
- return false;
-
- var target = this.findFloatingView(event.originalTarget);
- if (!target)
- return false;
-
- /* COVER YOUR EYES!! */
- var data = nsTransferable.get (this.getSupportedFlavours(),
- nsDragAndDrop.getDragData, true);
- data = data.first.first;
-
- var parsedLocation = this.parseLocation(data.data);
- if (target.getAttribute("id") == parsedLocation.id)
- return false;
-
- var direction = this.getDropDirection(event, target);
-
- if (target.parentNode.getAttribute("type") == "tab" &&
- direction.indexOf("tab") == -1)
- {
- // for tab views, up, down, left, and right are relative to the
- // tab container, *not* the view itself.
- target.parentNode.setAttribute ("dragover", direction);
- }
- else
- {
- target.setAttribute ("dragover", direction);
- target.proxyIcon.setAttribute ("dragover", direction);
-
- var tab = this.findViewTab(target);
- if (tab)
- tab.setAttribute("dragover", direction);
- }
-
- session.canDrop = true;
- return true;
- }
-
- ViewManager.prototype.onViewDragExit =
- function vmgr_dragexit (event, session)
- {
- var target = this.findFloatingView(event.originalTarget);
- if (target)
- {
- if (target.parentNode.getAttribute("type") == "tab")
- {
- // for tab views, up, down, left, and right are relative to the
- // tab container, *not* the view itself.
- target.parentNode.removeAttribute ("dragover");
- }
-
- target.removeAttribute ("dragover");
- target.proxyIcon.removeAttribute ("dragover");
- var tab = this.findViewTab(target);
- if (tab)
- tab.removeAttribute("dragover");
- }
- }
-
- ViewManager.prototype.onViewDrop =
- function vmgr_ondrop (event, transferData, session)
- {
- var viewManager = this;
-
- function callProcessDrop ()
- {
- viewManager.processDrop (sourceView, targetView, direction);
- };
-
- var floatingView = this.findFloatingView (event.originalTarget);
- var viewId = floatingView.getAttribute ("id");
- var targetView = this.views[viewId];
- if (!ASSERT("currentContent" in targetView,
- "view is not visible " + viewId))
- {
- return false;
- }
-
- var parsedSource = this.parseLocation(transferData.data);
- if (!ASSERT(parsedSource, "unable to parse " + transferData.data))
- return false;
-
- if (parsedSource.id == viewId)
- {
- //dd ("wanker");
- return false;
- }
-
- var sourceView = this.views[parsedSource.id];
-
- var direction = this.getDropDirection (event, floatingView);
-
- /* performing the actual drop action may involve moving DOM nodes
- * that are involved in the actual drag-drop operation. Mozilla
- * doesn't like it when you do that before drag-drop is done, so we
- * call ourselves back on a timer, to allow the drag-drop wind down before
- * modifying the DOM.
- */
- setTimeout (callProcessDrop, 1);
- return true;
- }
-
- ViewManager.prototype.processDrop =
- function vmgr_dewdropinn (sourceView, targetView, direction)
- {
- var viewManager = this;
-
- function reparent (child, type)
- {
- if (!ASSERT(child.parentNode.localName == "viewcontainer",
- "can't reparent child with unknown parent"))
- {
- return null;
- }
-
- var childLocation = viewManager.computeLocation(child);
- var id = "vm-container-" + ++viewManager.containerSequence;
- while (child.ownerDocument.getElementById(id))
- id = "vm-container-" + ++viewManager.containerSequence;
- var container = viewManager.createContainer (childLocation, id, type);
- var newLocation = { windowId: parsedTarget.windowId, containerId: id };
-
- if (child.localName == "floatingview")
- {
- viewManager.moveView (newLocation, childLocation.id);
- }
- else
- {
- viewManager.moveContainer (newLocation, child);
- }
-
- return container;
- };
-
- try {
-
- var destContainer;
- var destBefore;
- var currentContent = targetView.currentContent;
- var parsedTarget = this.computeLocation (currentContent);
- var currentContainer = currentContent.parentNode;
- var parentType = currentContainer.getAttribute("type");
-
- this.startMultiMove();
-
- if (direction.search(/^(new|next|prev)-tab$/) == 0)
- {
- if (parentType != "tab")
- destContainer = reparent(currentContent, "tab");
- else
- destContainer = currentContainer;
-
- if (direction == "new-tab")
- destBefore = null;
- else if (direction == "prev-tab")
- destBefore = currentContent;
- else if (direction == "next-tab")
- destBefore = currentContent.nextSibling;
- }
- else
- {
- if (parentType == "tab")
- {
- // tab containers can't accept up, down, left, right drops
- // directly. instead we defer to the tab container's container.
- currentContent = currentContainer;
- currentContainer = currentContainer.parentNode;
- if (!ASSERT(currentContainer.localName == "viewcontainer"))
- {
- this.endMultiMove();
- return;
- }
- parentType = currentContainer.getAttribute("type");
- }
-
- if (parentType == "vertical")
- {
- switch (direction)
- {
- case "up":
- destContainer = currentContainer;
- destBefore = currentContent;
- break;
-
- case "down":
- destContainer = currentContainer;
- destBefore = currentContent.nextSibling;
- if (destBefore && destBefore.hasAttribute("grout"))
- destBefore = destBefore.nextSibling;
- break;
-
- case "left":
- destContainer = reparent (currentContent, "horizontal");
- destBefore = currentContent;
- break;
-
- case "right":
- destContainer = reparent (currentContent, "horizontal");
- break;
- }
- }
- else if (parentType == "horizontal")
- {
- switch (direction)
- {
- case "up":
- destContainer = reparent (currentContent, "vertical");
- destBefore = currentContent;
- break;
-
- case "down":
- destContainer = reparent (currentContent, "vertical");
- break;
-
- case "left":
- destContainer = currentContainer;
- destBefore = currentContent;
- break;
-
- case "right":
- destContainer = currentContainer;
- destBefore = currentContent.nextSibling;
- if (destBefore && destBefore.hasAttribute("grout"))
- destBefore = destBefore.nextSibling;
- break;
- }
- }
- }
-
- var dest = new Object();
- dest.windowId = parsedTarget.windowId;
- dest.containerId = destContainer.getAttribute ("id");
- dest.before = destBefore ? destBefore.getAttribute("id") : null;
- this.moveView(dest, sourceView.viewId);
- this.endMultiMove();
-
- }
- catch (ex)
- {
- dd("caught exception: " + ex);
- dd(formatException(ex));
- }
- }
-